2.4 RunMainIsolate

这是函数定义。它接收脚本名称、包配置覆盖、是否强制禁用健全的空安全,以及 Dart 选项。

void RunMainIsolate(const char* script_name,
                    const char* package_config_override,
                    bool force_no_sound_null_safety,
                    CommandLineOptions* dart_options) {

如果提供了脚本名称,这段代码提取基本名称(不包含路径),然后设置进程名称为 "dart:[脚本基本名称]"。

  if (script_name != nullptr) {
    const char* base_name = strrchr(script_name, '/');
    if (base_name == nullptr) {
      base_name = script_name;
    } else {
      base_name++;  // Skip '/'.
    }
    const intptr_t kMaxNameLength = 64;
    char name[kMaxNameLength];
    Utils::SNPrint(name, kMaxNameLength, "dart:%s", base_name);
    Platform::SetProcessName(name);
  }

初始化一些变量,包括错误指针、退出代码和隔离标志。

  // Call CreateIsolateGroupAndSetup which creates an isolate and loads up
  // the specified application script.
  char* error = nullptr;
  int exit_code = 0;
  Dart_IsolateFlags flags;
  Dart_IsolateFlagsInitialize(&flags);

根据选项设置是否将主隔离标记为系统隔离。

  flags.is_system_isolate = Options::mark_main_isolate_as_system_isolate();

设置快照是否可以安全地使用 madvise(MADV_DONTNEED)。这在不同的操作系统和调试模式下有不同的行为。

  bool dontneed_safe = true;
#if defined(DART_HOST_OS_LINUX)
  // This would also be true in Linux, except that Google3 overrides the default
  // ELF interpreter to one that apparently doesn't create proper mappings.
  dontneed_safe = false;
#elif defined(DEBUG)
  // If the snapshot isn't file-backed, madvise(DONT_NEED) is destructive.
  if force_load_elf_from_memory() {
    dontneed_safe = false;
  }
#endif
  flags.snapshot_is_dontneed_safe = dontneed_safe;

创建主隔离组并进行设置。这是运行 Dart 代码的关键步骤。

  Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
      /* is_main_isolate */ true, script_name, "main",
      Options::packages_file() == nullptr ? package_config_override
                                          : Options::packages_file(),
      &flags, nullptr /* callback_data */, &error, &exit_code,
      force_no_sound_null_safety);

如果隔离创建失败,打印错误,清理资源,并退出程序。

  if (isolate == nullptr) {
    Syslog::PrintErr("%s\n", error);
    free(error);
    error = nullptr;
    Process::TerminateExitCodeHandler();
    error = Dart_Cleanup();
    if (error != nullptr) {
      Syslog::PrintErr("VM cleanup failed: %s\n", error);
      free(error);
    }
    dart::embedder::Cleanup();
    Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
  }

设置全局变量 main_isolate。

  main_isolate = isolate;

进入创建的隔离,并进行一些断言检查。

  Dart_EnterIsolate(isolate);
  ASSERT(isolate == Dart_CurrentIsolate());
  ASSERT(isolate != nullptr);
  Dart_Handle result;

进入一个新的 Dart 作用域。

  Dart_EnterScope();

断言确保不是在生成内核快照。

  // Kernel snapshots should have been handled before reaching this point.
  ASSERTgen_snapshot_kind() != kKernel;

获取根库的句柄。

  // Lookup the library of the root script.
  Dart_Handle root_lib = Dart_RootLibrary();

如果不是预编译运行时且设置了编译所有选项,则编译所有代码。

#if !defined(DART_PRECOMPILED_RUNTIME)
  if compile_all() {
    result = Dart_CompileAll();
    CHECK_RESULT(result);
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

如果找不到根库,报错并退出。

  if (Dart_IsNull(root_lib)) {
    ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
              script_name);
  }

获取 main 函数的闭包,并检查是否成功。

  // Create a closure for the main entry point which is in the exported
  // namespace of the root library or invoke a getter of the same name
  // in the exported namespace and return the resulting closure.
  Dart_Handle main_closure =
      Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
  CHECK_RESULT(main_closure);
  if (!Dart_IsClosure(main_closure)) {
    ErrorExit(kErrorExitCode, "Unable to find 'main' in root library '%s'\n",
              script_name);
  }

准备传递给 _startMainIsolate 的参数。

  // Call _startIsolate in the isolate library to enable dispatching the
  // initial startup message.
  const intptr_t kNumIsolateArgs = 2;
  Dart_Handle isolate_args[kNumIsolateArgs];
  isolate_args[0] = main_closure;                          // entryPoint
  isolate_args[1] = dart_options->CreateRuntimeOptions();  // args

查找 dart:isolate 库并调用 _startMainIsolate 函数来启动主隔离。

  Dart_Handle isolate_lib =
      Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
  result =
      Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startMainIsolate"),
                  kNumIsolateArgs, isolate_args);
  CHECK_RESULT(result);

运行 Dart 事件循环,直到最后一个活跃的接收端口关闭。

  // Keep handling messages until the last active receive port is closed.
  result = Dart_RunLoop();

如果需要生成 JIT 快照且没有编译错误,则生成快照。

  // Generate an app snapshot after execution if specified.
  if gen_snapshot_kind() == kAppJIT {
    if (!Dart_IsCompilationError(result)) {
      Snapshot::GenerateAppJITsnapshot_filename();
    }
  }
  CHECK_RESULT(result);

写入依赖文件(如果需要)。

  WriteDepsFile();

退出之前进入的 Dart 作用域。

  Dart_ExitScope();

关闭隔离。

  // Shutdown the isolate.
  Dart_ShutdownIsolate();
}

本文作者:Maeiee

本文链接:2.4 RunMainIsolate

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!